home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Resources / Online / Term / Extras / Source / term-source.lha / Matrix.c < prev    next >
C/C++ Source or Header  |  1996-10-20  |  18KB  |  837 lines

  1. /*
  2. **    Matrix.c
  3. **
  4. **    Single character entry
  5. **
  6. **    Copyright © 1990-1996 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. **
  9. **    :ts=4
  10. */
  11.  
  12. #ifndef _GLOBAL_H
  13. #include "Global.h"
  14. #endif
  15.  
  16. #define MIA_CellWidth    (TAG_USER+0x70000)
  17. #define MIA_CellHeight    (TAG_USER+0x70001)
  18. #define MIA_Width        (TAG_USER+0x70002)
  19. #define MIA_Height        (TAG_USER+0x70003)
  20. #define MIA_Labels        (TAG_USER+0x70004)
  21. #define MIA_NumLabels    (TAG_USER+0x70005)
  22. #define MIA_Font        (TAG_USER+0x70006)
  23. #define MIA_Index        (TAG_USER+0x70007)
  24.  
  25. typedef struct MatrixInfo
  26. {
  27.     UWORD             CellWidth,
  28.                      CellHeight;
  29.     UWORD             Width,
  30.                      Height;
  31.     UWORD             PixelWidth,
  32.                      PixelHeight;
  33.     WORD             CurrentX,
  34.                      CurrentY;
  35.     STRPTR            *Labels;
  36.     LONG             NumLabels;
  37.     struct TextFont    *Font;
  38. } MatrixInfo;
  39.  
  40. STATIC Class        *MatrixClass;
  41. STATIC Object        *MatrixGadget;
  42.  
  43. STATIC UBYTE         TitleBuffer[256];
  44.  
  45. STATIC VOID
  46. DrawCellText(struct RastPort *RPort,LONG Left,LONG Top,LONG Width,LONG Height,STRPTR Label)
  47. {
  48.     struct TextExtent Extent;
  49.     LONG Len;
  50.  
  51.     if(Len = TextFit(RPort,Label,strlen(Label),&Extent,NULL,1,Width,32767))
  52.         PlaceText(RPort,Left + (Width - Extent.te_Width) / 2,Top + (Height - Extent.te_Height) / 2,Label,Len);
  53. }
  54.  
  55. STATIC VOID
  56. DrawCell(struct RastPort *RPort,LONG PixelLeft,LONG PixelTop,UWORD *Pens,MatrixInfo *Info,LONG x,LONG y,BOOL Highlight)
  57. {
  58.     UWORD Shine,Shadow,Text,Fill;
  59.     LONG Left,Top;
  60.     LONG Index;
  61.  
  62.     Left    = PixelLeft    + Info->CellWidth    * x;
  63.     Top        = PixelTop    + Info->CellHeight    * y;
  64.  
  65.     if(Highlight)
  66.     {
  67.         Shine    = SHADOWPEN;
  68.         Shadow    = SHINEPEN;
  69.         Text    = FILLTEXTPEN;
  70.         Fill    = FILLPEN;
  71.     }
  72.     else
  73.     {
  74.         Shine    = SHINEPEN;
  75.         Shadow    = SHADOWPEN;
  76.         Text    = TEXTPEN;
  77.         Fill    = BACKGROUNDPEN;
  78.     }
  79.  
  80.     SetDrMd(RPort,JAM1);
  81.  
  82.     SetAPen(RPort,Pens[Shine]);
  83.     Move(RPort,Left,Top + Info->CellHeight - 1);
  84.     Draw(RPort,Left,Top);
  85.     Draw(RPort,Left + Info->CellWidth - 1,Top);
  86.  
  87.     SetAPen(RPort,Pens[Shadow]);
  88.     Move(RPort,Left + 1,Top + Info->CellHeight - 1);
  89.     Draw(RPort,Left + Info->CellWidth - 1,Top + Info->CellHeight - 1);
  90.     Draw(RPort,Left + Info->CellWidth - 1,Top + 1);
  91.  
  92.     SetAPen(RPort,Pens[Fill]);
  93.     RectFill(RPort,Left + 1,Top + 1,Left + Info->CellWidth - 2,Top + Info->CellHeight - 2);
  94.  
  95.     if((Index = y * Info->Width + x) < Info->NumLabels)
  96.     {
  97.         SetAPen(RPort,Pens[Text]);
  98.         DrawCellText(RPort,Left + 1,Top + 1,Info->CellWidth - 2,Info->CellHeight - 2,Info->Labels[Index]);
  99.     }
  100. }
  101.  
  102. STATIC VOID
  103. DrawGrid(struct RastPort *RPort,LONG PixelLeft,LONG PixelTop,UWORD *Pens,MatrixInfo *Info)
  104. {
  105.     LONG i,j,Left,Top,Bottom,Strange,Charm;
  106.  
  107.     SetDrMd(RPort,JAM1);
  108.  
  109.     Left    = PixelLeft;
  110.     Top        = PixelTop;
  111.     Bottom    = PixelTop + Info->PixelHeight - 1;
  112.  
  113.     Strange    = Pens[SHINEPEN];
  114.     Charm    = Pens[SHADOWPEN];
  115.  
  116.     for(i = 0 ; i < Info->Width ; i++)
  117.     {
  118.         SetAPen(RPort,Strange);
  119.         Move(RPort,Left,Top);
  120.         Draw(RPort,Left,Bottom);
  121.  
  122.         Left += Info->CellWidth;
  123.  
  124.         SetAPen(RPort,Charm);
  125.         Move(RPort,Left - 1,Top);
  126.         Draw(RPort,Left - 1,Bottom);
  127.     }
  128.  
  129.     Top = PixelTop;
  130.  
  131.     for(j = 0 ; j < Info->Height ; j++)
  132.     {
  133.         Left = PixelLeft;
  134.  
  135.         for(i = 0 ; i < Info->Width ; i++)
  136.         {
  137.             SetAPen(RPort,Strange);
  138.             Move(RPort,Left,Top);
  139.             Draw(RPort,Left + Info->CellWidth - 1,Top);
  140.  
  141.             SetAPen(RPort,Charm);
  142.             Move(RPort,Left + 1,Top + Info->CellHeight - 1);
  143.             Draw(RPort,Left + Info->CellWidth - 2,Top + Info->CellHeight - 1);
  144.  
  145.             Left += Info->CellWidth;
  146.         }
  147.  
  148.         Top += Info->CellHeight;
  149.     }
  150. }
  151.  
  152. STATIC VOID
  153. NotifyIndex(Class *class,Object *object,struct GadgetInfo *GInfo,struct opUpdate *msg,LONG Index)
  154. {
  155.     struct TagItem Tags[3];
  156.  
  157.     Tags[0].ti_Tag    = MIA_Index;
  158.     Tags[0].ti_Data    = Index;
  159.     Tags[1].ti_Tag    = GA_ID;
  160.     Tags[1].ti_Data    = ((struct Gadget *)object)->GadgetID;
  161.     Tags[2].ti_Tag    = TAG_DONE;
  162.  
  163.     DoSuperMethod(class,object,OM_NOTIFY,Tags,GInfo,((msg->MethodID == OM_UPDATE) ? (msg->opu_Flags) : 0L));
  164. }
  165.  
  166. STATIC BOOL
  167. SetMethod(Class *class,Object *object,struct opSet *SetInfo)
  168. {
  169.     struct TagItem *Tag;
  170.     MatrixInfo *Info;
  171.  
  172.     Info = INST_DATA(class,object);
  173.  
  174.     if(Tag = FindTagItem(MIA_Index,SetInfo->ops_AttrList))
  175.     {
  176.         struct RastPort *RPort;
  177.  
  178.         if(RPort = ObtainGIRPort(SetInfo->ops_GInfo))
  179.         {
  180.             UWORD *Pens;
  181.             LONG Index;
  182.  
  183.             Index    = (LONG)Tag->ti_Data;
  184.             Pens    = SetInfo->ops_GInfo->gi_DrInfo->dri_Pens;
  185.  
  186.             SetFont(RPort,Info->Font);
  187.  
  188.             if(Info->CurrentX != -1 && Info->CurrentY !=-1)
  189.                 DrawCell(RPort,((struct Gadget *)object)->LeftEdge,((struct Gadget *)object)->TopEdge,Pens,Info,Info->CurrentX,Info->CurrentY,FALSE);
  190.  
  191.             if(Index >= 0 && Index < Info->Width * Info->Height)
  192.             {
  193.                 Info->CurrentX = Index % Info->Width;
  194.                 Info->CurrentY = Index / Info->Width;
  195.  
  196.                 DrawCell(RPort,((struct Gadget *)object)->LeftEdge,((struct Gadget *)object)->TopEdge,Pens,Info,Info->CurrentX,Info->CurrentY,TRUE);
  197.  
  198.                 NotifyIndex(class,object,SetInfo->ops_GInfo,(struct opUpdate *)SetInfo,Index);
  199.             }
  200.             else
  201.             {
  202.                 Info->CurrentX = Info->CurrentY = -1;
  203.  
  204.                 NotifyIndex(class,object,SetInfo->ops_GInfo,(struct opUpdate *)SetInfo,-1);
  205.             }
  206.  
  207.             ReleaseGIRPort(RPort);
  208.  
  209.             return(TRUE);
  210.         }
  211.     }
  212.  
  213.     return(FALSE);
  214. }
  215.  
  216. STATIC ULONG
  217. RenderMethod(Class *class,Object *object,struct gpRender *RenderInfo)
  218. {
  219.     LONG i,x,y,Left,Top;
  220.     MatrixInfo *Info;
  221.     UWORD *Pens;
  222.  
  223.     Info = INST_DATA(class,object);
  224.     Pens = RenderInfo->gpr_GInfo->gi_DrInfo->dri_Pens;
  225.  
  226.     SetFont(RenderInfo->gpr_RPort,Info->Font);
  227.  
  228.     Left    = ((struct Gadget *)object)->LeftEdge;
  229.     Top        = ((struct Gadget *)object)->TopEdge;
  230.  
  231.     SetAPen(RenderInfo->gpr_RPort,Pens[BACKGROUNDPEN]);
  232.     FillBox(RenderInfo->gpr_RPort,Left,Top,((struct Gadget *)object)->Width,((struct Gadget *)object)->Height);
  233.  
  234.     DrawGrid(RenderInfo->gpr_RPort,Left,Top,Pens,Info);
  235.  
  236.     SetAPen(RenderInfo->gpr_RPort,Pens[TEXTPEN]);
  237.  
  238.     for(i = 0 ; i < Info->NumLabels ; i++)
  239.     {
  240.         x = (i % Info->Width) * Info->CellWidth;
  241.         y = (i / Info->Width) * Info->CellHeight;
  242.  
  243.         DrawCellText(RenderInfo->gpr_RPort,Left + x,Top + y,Info->CellWidth,Info->CellHeight,Info->Labels[i]);
  244.     }
  245.  
  246.     return(TRUE);
  247. }
  248.  
  249. STATIC VOID
  250. DisposeMethod(Class *class,Object *object,Msg UnusedMsg)
  251. {
  252.     MatrixInfo *Info = INST_DATA(class,object);
  253.  
  254.     if(Info->Font)
  255.         CloseFont(Info->Font);
  256. }
  257.  
  258. STATIC ULONG
  259. NewMethod(Class *class,Object *object,struct opSet *SetInfo)
  260. {
  261.     if(object = (Object *)DoSuperMethodA(class,object,(Msg)SetInfo))
  262.     {
  263.         struct TagItem    *Tag,*TagList;
  264.         LONG             Width,Height;
  265.         MatrixInfo        *Info;
  266.         struct TextAttr    *Font;
  267.  
  268.         Info    = INST_DATA(class,object);
  269.         TagList    = SetInfo->ops_AttrList;
  270.         Width    = 0;
  271.         Height    = 0;
  272.         Font    = NULL;
  273.  
  274.         memset(Info,0,sizeof(MatrixInfo));
  275.  
  276.         while(Tag = NextTagItem(&TagList))
  277.         {
  278.             switch(Tag->ti_Tag)
  279.             {
  280.                 case MIA_CellWidth:
  281.  
  282.                     Info->CellWidth = Tag->ti_Data;
  283.                     break;
  284.  
  285.                 case MIA_CellHeight:
  286.  
  287.                     Info->CellHeight = Tag->ti_Data;
  288.                     break;
  289.  
  290.                 case MIA_Width:
  291.  
  292.                     Info->Width = Tag->ti_Data;
  293.                     break;
  294.  
  295.                 case MIA_Height:
  296.  
  297.                     Info->Height = Tag->ti_Data;
  298.                     break;
  299.  
  300.                 case MIA_Labels:
  301.  
  302.                     Info->Labels = (STRPTR *)Tag->ti_Data;
  303.                     break;
  304.  
  305.                 case MIA_NumLabels:
  306.  
  307.                     Info->NumLabels = Tag->ti_Data;
  308.                     break;
  309.  
  310.                 case MIA_Font:
  311.  
  312.                     Font = (struct TextAttr *)Tag->ti_Data;
  313.                     break;
  314.  
  315.                 case GA_Width:
  316.  
  317.                     Width = Tag->ti_Data;
  318.                     break;
  319.  
  320.                 case GA_Height:
  321.  
  322.                     Height = Tag->ti_Data;
  323.                     break;
  324.             }
  325.         }
  326.  
  327.         if(Info->Labels && !Info->NumLabels)
  328.         {
  329.             while(Info->Labels[Info->NumLabels])
  330.                 Info->NumLabels++;
  331.         }
  332.  
  333.         if(Font && Info->CellWidth && Info->CellHeight)
  334.         {
  335.             if(!Info->Width)
  336.                 Info->Width = Width / Info->CellWidth;
  337.  
  338.             if(!Info->Height)
  339.                 Info->Height = Height / Info->CellHeight;
  340.  
  341.             if(Info->Width && Info->Height)
  342.             {
  343.                 if(Info->Font = OpenFont(Font))
  344.                 {
  345.                     Info->CurrentX        = -1;
  346.                     Info->CurrentY        = -1;
  347.                     Info->PixelWidth    = Info->Width    * Info->CellWidth;
  348.                     Info->PixelHeight    = Info->Height    * Info->CellHeight;
  349.  
  350.                     return((ULONG)object);
  351.                 }
  352.             }
  353.         }
  354.  
  355.         CoerceMethod(class,object,OM_DISPOSE);
  356.     }
  357.  
  358.     return(0);
  359. }
  360.  
  361. STATIC ULONG
  362. InputMethod(Class *class,Object *object,struct gpInput *InputInfo)
  363. {
  364.     MatrixInfo *Info;
  365.     ULONG Result;
  366.     UWORD *Pens;
  367.     BOOL Done;
  368.     LONG x,y;
  369.  
  370.     Info    = INST_DATA(class,object);
  371.     Result    = GMR_MEACTIVE;
  372.     Pens    = InputInfo->gpi_GInfo->gi_DrInfo->dri_Pens;
  373.     Done    = FALSE;
  374.  
  375.     if(InputInfo->gpi_IEvent->ie_Class == IECLASS_RAWMOUSE)
  376.     {
  377.         if(InputInfo->gpi_IEvent->ie_Code == MENUDOWN)
  378.         {
  379.             Result    = GMR_NOREUSE;
  380.             Done    = TRUE;
  381.         }
  382.         else
  383.         {
  384.             if(InputInfo->gpi_IEvent->ie_Code == SELECTUP)
  385.             {
  386.                 Done = TRUE;
  387.  
  388.                 if(Info->CurrentX != -1 && Info->CurrentY != -1)
  389.                 {
  390.                     Result = GMR_REUSE | GMR_VERIFY;
  391.  
  392.                     *InputInfo->gpi_Termination = Info->CurrentY * Info->Width + Info->CurrentX;
  393.                 }
  394.                 else
  395.                     Result = GMR_NOREUSE;
  396.             }
  397.         }
  398.  
  399.         if(Done && Info->CurrentX != -1 && Info->CurrentY != -1)
  400.         {
  401.             struct RastPort    *RPort;
  402.  
  403.             if(RPort = ObtainGIRPort(InputInfo->gpi_GInfo))
  404.             {
  405.                 SetFont(RPort,Info->Font);
  406.  
  407.                 DrawCell(RPort,((struct Gadget *)object)->LeftEdge,((struct Gadget *)object)->TopEdge,Pens,Info,Info->CurrentX,Info->CurrentY,FALSE);
  408.  
  409.                 Info->CurrentX    = -1;
  410.                 Info->CurrentY    = -1;
  411.  
  412.                 ReleaseGIRPort(RPort);
  413.  
  414.                 NotifyIndex(class,object,InputInfo->gpi_GInfo,(struct opUpdate *)InputInfo,-1);
  415.             }
  416.         }
  417.     }
  418.  
  419.     if(!Done)
  420.     {
  421.         x = InputInfo->gpi_Mouse.X / Info->CellWidth;
  422.         y = InputInfo->gpi_Mouse.Y / Info->CellHeight;
  423.  
  424.         if(InputInfo->gpi_Mouse.X < 0 || InputInfo->gpi_Mouse.Y < 0 || x >= Info->Width || y >= Info->Height)
  425.             x = y = -1;
  426.  
  427.         if(x != Info->CurrentX || y != Info->CurrentY)
  428.         {
  429.             struct RastPort    *RPort;
  430.  
  431.             if(RPort = ObtainGIRPort(InputInfo->gpi_GInfo))
  432.             {
  433.                 SetFont(RPort,Info->Font);
  434.  
  435.                 if(Info->CurrentX != -1 && Info->CurrentY != -1)
  436.                     DrawCell(RPort,((struct Gadget *)object)->LeftEdge,((struct Gadget *)object)->TopEdge,Pens,Info,Info->CurrentX,Info->CurrentY,FALSE);
  437.  
  438.                 Info->CurrentX    = x;
  439.                 Info->CurrentY    = y;
  440.  
  441.                 if(x != -1 && y != -1)
  442.                 {
  443.                     DrawCell(RPort,((struct Gadget *)object)->LeftEdge,((struct Gadget *)object)->TopEdge,Pens,Info,Info->CurrentX,Info->CurrentY,TRUE);
  444.  
  445.                     NotifyIndex(class,object,InputInfo->gpi_GInfo,(struct opUpdate *)InputInfo,y * Info->Width + x);
  446.                 }
  447.                 else
  448.                     NotifyIndex(class,object,InputInfo->gpi_GInfo,(struct opUpdate *)InputInfo,-1);
  449.  
  450.                 ReleaseGIRPort(RPort);
  451.             }
  452.         }
  453.     }
  454.  
  455.     return(Result);
  456. }
  457.  
  458. STATIC ULONG
  459. ActiveMethod(Class *class,Object *object,struct gpInput *InputInfo)
  460. {
  461.     struct RastPort    *RPort;
  462.  
  463.     if(RPort = ObtainGIRPort(InputInfo->gpi_GInfo))
  464.     {
  465.         MatrixInfo *Info;
  466.         UWORD *Pens;
  467.  
  468.         Info = INST_DATA(class,object);
  469.         Pens = InputInfo->gpi_GInfo->gi_DrInfo->dri_Pens;
  470.  
  471.         SetFont(RPort,Info->Font);
  472.  
  473.         if(Info->CurrentX != -1 && Info->CurrentY !=-1)
  474.             DrawCell(RPort,((struct Gadget *)object)->LeftEdge,((struct Gadget *)object)->TopEdge,Pens,Info,Info->CurrentX,Info->CurrentY,FALSE);
  475.  
  476.         Info->CurrentX = InputInfo->gpi_Mouse.X / Info->CellWidth;
  477.         Info->CurrentY = InputInfo->gpi_Mouse.Y / Info->CellHeight;
  478.  
  479.         if(Info->CurrentX > Info->Width - 1)
  480.             Info->CurrentX = Info->Width - 1;
  481.         else
  482.         {
  483.             if(Info->CurrentX < 0)
  484.                 Info->CurrentX = 0;
  485.         }
  486.  
  487.         if(Info->CurrentY > Info->Height - 1)
  488.             Info->CurrentY = Info->Height - 1;
  489.         else
  490.         {
  491.             if(Info->CurrentY < 0)
  492.                 Info->CurrentY = 0;
  493.         }
  494.  
  495.         DrawCell(RPort,((struct Gadget *)object)->LeftEdge,((struct Gadget *)object)->TopEdge,Pens,Info,Info->CurrentX,Info->CurrentY,TRUE);
  496.  
  497.         NotifyIndex(class,object,InputInfo->gpi_GInfo,(struct opUpdate *)InputInfo,Info->CurrentY * Info->Width + Info->CurrentX);
  498.  
  499.         ReleaseGIRPort(RPort);
  500.  
  501.         return(GMR_MEACTIVE);
  502.     }
  503.     else
  504.         return(GMR_NOREUSE);
  505. }
  506.  
  507. STATIC ULONG
  508. InactiveMethod(Class *class,Object *object,struct gpGoInactive *InactiveInfo)
  509. {
  510.     MatrixInfo *Info = INST_DATA(class,object);
  511.  
  512.     if(Info->CurrentX != -1 && Info->CurrentY != -1)
  513.     {
  514.         struct RastPort    *RPort;
  515.  
  516.         if(RPort = ObtainGIRPort(InactiveInfo->gpgi_GInfo))
  517.         {
  518.             SetFont(RPort,Info->Font);
  519.  
  520.             DrawCell(RPort,((struct Gadget *)object)->LeftEdge,((struct Gadget *)object)->TopEdge,InactiveInfo->gpgi_GInfo->gi_DrInfo->dri_Pens,Info,Info->CurrentX,Info->CurrentY,FALSE);
  521.  
  522.             ReleaseGIRPort(RPort);
  523.  
  524.             NotifyIndex(class,object,InactiveInfo->gpgi_GInfo,(struct opUpdate *)InactiveInfo,-1);
  525.         }
  526.     }
  527.  
  528.     Info->CurrentX = -1;
  529.     Info->CurrentY = -1;
  530.  
  531.     return(0);
  532. }
  533.  
  534. STATIC ULONG
  535. HitTestMethod(Class *class,Object *object,struct gpHitTest *HitInfo)
  536. {
  537.     MatrixInfo *Info = INST_DATA(class,object);
  538.  
  539.     if(HitInfo->gpht_Mouse.X < Info->PixelWidth && HitInfo->gpht_Mouse.Y < Info->PixelHeight)
  540.         return(GMR_GADGETHIT);
  541.     else
  542.         return(0);
  543. }
  544.  
  545. STATIC ULONG SAVE_DS ASM
  546. Dispatch(REG(a0) Class *class,REG(a2) Object *object,REG(a1) Msg msg)
  547. {
  548.     switch(msg->MethodID)
  549.     {
  550.         case OM_NEW:
  551.  
  552.             return(NewMethod(class,object,(struct opSet *)msg));
  553.  
  554.         case OM_UPDATE:
  555.         case OM_SET:
  556.  
  557.             if(SetMethod(class,object,(struct opSet *)msg))
  558.                 return(TRUE);
  559.             else
  560.                 break;
  561.  
  562.         case GM_RENDER:
  563.  
  564.             return(RenderMethod(class,object,(struct gpRender *)msg));
  565.  
  566.         case GM_HITTEST:
  567.  
  568.             return(HitTestMethod(class,object,(struct gpHitTest *)msg));
  569.  
  570.         case GM_GOINACTIVE:
  571.  
  572.             return(InactiveMethod(class,object,(struct gpGoInactive *)msg));
  573.  
  574.         case GM_GOACTIVE:
  575.  
  576.             return(ActiveMethod(class,object,(struct gpInput *)msg));
  577.  
  578.         case GM_HANDLEINPUT:
  579.  
  580.             return(InputMethod(class,object,(struct gpInput *)msg));
  581.  
  582.         case OM_DISPOSE:
  583.  
  584.             DisposeMethod(class,object,msg);
  585.     }
  586.  
  587.     return(DoSuperMethodA(class,object,msg));
  588. }
  589.  
  590. STATIC VOID
  591. DeleteMatrixClass(VOID)
  592. {
  593.     if(MatrixClass)
  594.     {
  595.         FreeClass(MatrixClass);
  596.         MatrixClass = NULL;
  597.     }
  598. }
  599.  
  600. STATIC Class *
  601. CreateMatrixClass(VOID)
  602. {
  603.     if(MatrixClass = MakeClass(NULL,GADGETCLASS,NULL,sizeof(MatrixInfo),0))
  604.         InitHook(&MatrixClass->cl_Dispatcher,(HOOKFUNC)Dispatch,NULL);
  605.  
  606.     return(MatrixClass);
  607. }
  608.  
  609. VOID
  610. CloseMatrixWindow()
  611. {
  612.     CheckItem(MEN_MATRIX_WINDOW,FALSE);
  613.  
  614.     if(MatrixWindow)
  615.     {
  616.         PutWindowInfo(WINDOW_CHARTAB,MatrixWindow->LeftEdge,MatrixWindow->TopEdge,MatrixWindow->Width,MatrixWindow->Height);
  617.  
  618.         ClearMenuStrip(MatrixWindow);
  619.  
  620.         CloseWindowSafely(MatrixWindow);
  621.  
  622.         MatrixWindow = NULL;
  623.     }
  624.  
  625.     if(MatrixGadget)
  626.     {
  627.         DisposeObject(MatrixGadget);
  628.  
  629.         MatrixGadget = NULL;
  630.     }
  631.  
  632.     DeleteMatrixClass();
  633. }
  634.  
  635. BOOL
  636. DispatchMatrixWindow(ULONG *MsgClass,UWORD MsgCode,ULONG MsgQualifier,UBYTE Char)
  637. {
  638.     if(MatrixWindow)
  639.     {
  640.         switch(*MsgClass)
  641.         {
  642.             case IDCMP_RAWKEY:
  643.  
  644.                 if(!(MsgCode & IECODE_UP_PREFIX) && !(MsgQualifier & IEQUALIFIER_REPEAT) && !(MsgCode >= CURSOR_UP_CODE && MsgCode <= F10_CODE) && !(MsgCode >= HELP_CODE && MsgCode <= RAMIGA_CODE))
  645.                 {
  646.                     SetGadgetAttrs((struct Gadget *)MatrixGadget,MatrixWindow,NULL,
  647.                         MIA_Index,    Char,
  648.                     TAG_DONE);
  649.  
  650.                     Delay(TICKS_PER_SECOND / 10);
  651.  
  652.                     SetGadgetAttrs((struct Gadget *)MatrixGadget,MatrixWindow,NULL,
  653.                         MIA_Index,    -1,
  654.                     TAG_DONE);
  655.                 }
  656.  
  657.                 break;
  658.  
  659.             case IDCMP_CLOSEWINDOW:
  660.  
  661.                 *MsgClass = 0;
  662.  
  663.                 return(TRUE);
  664.  
  665.             case IDCMP_GADGETUP:
  666.  
  667.                 *MsgClass = 0;
  668.  
  669.                 Char = MsgCode;
  670.  
  671.                 SerWrite(&Char,1);
  672.  
  673.                 break;
  674.  
  675.             case IDCMP_IDCMPUPDATE:
  676.  
  677.                 *MsgClass = 0;
  678.  
  679.                 if((WORD)MsgCode < 0)
  680.                     SetWindowTitles(MatrixWindow,LocaleString(MSG_MATRIX_WINDOW_TITLE),(STRPTR)~0);
  681.                 else
  682.                 {
  683.                     UBYTE    OctalBuffer[6],BinBuffer[10];
  684.                     LONG    i,Code;
  685.  
  686.                     OctalBuffer[0] = '0';
  687.  
  688.                     for(Code = MsgCode, i = 0 ; i < 3 ; i++)
  689.                     {
  690.                         OctalBuffer[2 - i + 1] = '0' + (Code & 7);
  691.  
  692.                         Code = Code >> 3;
  693.                     }
  694.  
  695.                     OctalBuffer[4] = 0;
  696.  
  697.                     BinBuffer[0] = '%';
  698.  
  699.                     for(Code = MsgCode, i = 0 ; i < 8 ; i++)
  700.                     {
  701.                         BinBuffer[7 - i + 1] = '0' + (Code & 1);
  702.  
  703.                         Code = Code >> 1;
  704.                     }
  705.  
  706.                     BinBuffer[9] = 0;
  707.  
  708.                     LimitedSPrintf(sizeof(TitleBuffer),TitleBuffer,"%s [%ld · $%02lx · %s · %s]",LocaleString(MSG_MATRIX_WINDOW_TITLE),MsgCode,MsgCode,OctalBuffer,BinBuffer);
  709.  
  710.                     SetWindowTitles(MatrixWindow,TitleBuffer,(STRPTR)~0);
  711.                 }
  712.  
  713.                 break;
  714.         }
  715.     }
  716.  
  717.     return(FALSE);
  718. }
  719.  
  720. struct Window *
  721. OpenMatrixWindow(struct Window *Parent)
  722. {
  723.     if(MatrixWindow)
  724.     {
  725.         WindowToFront(MatrixWindow);
  726.  
  727.         ActivateWindow(MatrixWindow);
  728.  
  729.         return(MatrixWindow);
  730.     }
  731.     else
  732.     {
  733.         LONG i,MaxWidth,Width,Height;
  734.         struct RastPort RastPort;
  735.         struct TextFont *Font;
  736.  
  737.         InitRastPort(&RastPort);
  738.         Font = OpenFont((struct TextAttr *)&TextAttr);
  739.         SetFont(&RastPort,Font);
  740.  
  741.         for(i = 0, MaxWidth = 0 ; i < 256 ; i++)
  742.         {
  743.             if((Width = TextLength(&RastPort,CharCodes[i],strlen(CharCodes[i]))) > MaxWidth)
  744.                 MaxWidth = Width;
  745.         }
  746.  
  747.         Width    = 2 + MaxWidth + 2;
  748.         Height    = 2 + RastPort.TxHeight + 2;
  749.  
  750.         if(Parent->WScreen->WBorTop + Parent->WScreen->Font->ta_YSize + 1 + Parent->WScreen->WBorBottom + 16 * Height > Parent->WScreen->Height || Parent->WScreen->WBorLeft + 16 * Width + Parent->WScreen->WBorRight > Parent->WScreen->Width)
  751.         {
  752.             DisplayBeep(Parent->WScreen);
  753.  
  754.             return(NULL);
  755.         }
  756.  
  757.         if(CreateMatrixClass())
  758.         {
  759.             STATIC Tag Map[] = { MIA_Index, ICSPECIAL_CODE, TAG_DONE };
  760.  
  761.             if(MatrixGadget = NewObject(MatrixClass,NULL,
  762.                 GA_Left,            Parent->WScreen->WBorLeft + 2,
  763.                 GA_Top,                Parent->WScreen->WBorTop + Parent->WScreen->Font->ta_YSize + 1 + 2,
  764.                 GA_Width,            16 * Width,
  765.                 GA_Height,            16 * Height,
  766.                 GA_RelVerify,        TRUE,
  767.  
  768.                 ICA_TARGET,            ICTARGET_IDCMP,
  769.                 ICA_MAP,            Map,
  770.  
  771.                 MIA_Width,            16,
  772.                 MIA_Height,            16,
  773.                 MIA_CellWidth,        Width,
  774.                 MIA_CellHeight,        Height,
  775.                 MIA_Labels,            CharCodes,
  776.                 MIA_NumLabels,        256,
  777.                 MIA_Font,            &TextAttr,
  778.             TAG_DONE))
  779.             {
  780.                 LONG Left,Top,DummyWidth,DummyHeight;
  781.  
  782.                 Left = Top = DummyWidth = DummyHeight = 0;
  783.  
  784.                 GetWindowInfo(WINDOW_CHARTAB,&Left,&Top,&DummyWidth,&DummyHeight,0,0);
  785.  
  786.                 if(MatrixWindow = OpenWindowTags(NULL,
  787.                     WA_Top,                Left,
  788.                     WA_Left,            Top,
  789.                     WA_Title,            LocaleString(MSG_MATRIX_WINDOW_TITLE),
  790.                     WA_DepthGadget,        TRUE,
  791.                     WA_CloseGadget,        TRUE,
  792.                     WA_DragBar,            TRUE,
  793.                     WA_InnerWidth,        2 + (Width * 16) + 2,
  794.                     WA_InnerHeight,        2 + (Height * 16) + 2,
  795.                     WA_Activate,        TRUE,
  796.                     WA_Gadgets,            MatrixGadget,
  797.                     OpenWindowTag,        Parent->WScreen,
  798.                     WA_NewLookMenus,    TRUE,
  799.                     BackfillTag,        &BackfillHook,
  800.                     WA_SimpleRefresh,    TRUE,
  801.  
  802.                     AmigaGlyph ? WA_AmigaKey  : TAG_IGNORE, AmigaGlyph,
  803.                     CheckGlyph ? WA_Checkmark : TAG_IGNORE, CheckGlyph,
  804.                 TAG_DONE))
  805.                 {
  806.                     MatrixWindow->UserPort = Parent->UserPort;
  807.  
  808.                     if(ModifyIDCMP(MatrixWindow,Parent->IDCMPFlags | IDCMP_CLOSEWINDOW | IDCMP_GADGETUP | IDCMP_IDCMPUPDATE | IDCMP_REFRESHWINDOW))
  809.                     {
  810.                         SetMenuStrip(MatrixWindow,Menu);
  811.  
  812.                         CheckItem(MEN_MATRIX_WINDOW,TRUE);
  813.  
  814.                         return(MatrixWindow);
  815.                     }
  816.  
  817.                     MatrixWindow->UserPort = NULL;
  818.  
  819.                     CloseWindow(MatrixWindow);
  820.  
  821.                     MatrixWindow = NULL;
  822.                 }
  823.  
  824.                 DisposeObject(MatrixGadget);
  825.  
  826.                 MatrixGadget = NULL;
  827.             }
  828.  
  829.             DeleteMatrixClass();
  830.         }
  831.  
  832.         CheckItem(MEN_MATRIX_WINDOW,FALSE);
  833.  
  834.         return(NULL);
  835.     }
  836. }
  837.